﻿using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Reflection;
using System.Windows.Forms;
using rlTodayMakeSkin.GUI;
using rlTodayMakeSkin.Project.Attributes;
using rlTodayMakeSkin.Project.XmlElement;
using rlTodayMakeSkin.Project.XmlElement.Properties;
using rlTodayMakeSkin.Project.XmlElement.XmlSubElements;

namespace rlTodayMakeSkin.GUI
{
    /// <summary>
    /// Display each xml element in skin display
    /// </summary>
    public class SkinControl : PictureBox
    {
        private rlTodayXmlElement myEl;
        private bool isSelected = false;
        private Bitmap btBack = null;

        public SkinControl(rlTodayXmlElement element)
        {
            myEl = element;
            this.MouseMove += new MouseEventHandler(SelectedControlsManager.GetManager().Mouse_Move);
            this.MouseUp += new MouseEventHandler(SelectedControlsManager.GetManager().Mouse_Up);
            this.MouseDown += new MouseEventHandler(SelectedControlsManager.GetManager().Mouse_Down);
            this.KeyDown += new KeyEventHandler(SelectedControlsManager.GetManager().Key_Down);

            myEl.SetGuiControl(this);
            //Update control size and position
            Height = myEl.Height;
            Width = myEl.Width;
            btBack = new Bitmap(Width, Height);
            Location = new Point(myEl.X, myEl.Y);
            DrawControl();
        }

        public rlTodayXmlElement SkinElement
        {
            get { return myEl; }
            set { myEl = value; }
        }

        /// <summary>
        /// Gets, sets a bool value that indicates if this control is currently
        /// selected and performs actions to change its view
        /// </summary>
        public bool Selected
        {
            get { return isSelected; }
            set { 
                isSelected = value;
                DrawControl();
            }
        }

        /// <summary>
        /// Gets sets skin control height
        /// </summary>
        /// <remarks>updates height of associated rlTodayXmlElement</remarks>
        public new int Height
        {
            get { return base.Height; }
            set { 
                base.Height = value; 
                myEl.Height = value;
                
            }
        }

        /// <summary>
        /// Gets sets skin control width
        /// </summary>
        /// <remarks>updates width of associated rlTodayXmlElement</remarks>
        public new int Width
        {
            get { return base.Width; }
            set { 
                base.Width = value;
                myEl.Width = value;
            }
        }

        /// <summary>
        /// Gets sets skin control left
        /// </summary>
        /// <remarks>updates x position of associated rlTodayXmlElement</remarks>
        public new int Left
        {
            get { return base.Left; }
            set
            {
                base.Left = value;
                myEl.X = value;
            }
        }

        /// <summary>
        /// Gets sets skin control top
        /// </summary>
        /// <remarks>updates y position of associated rlTodayXmlElement</remarks>
        public new int Top
        {
            get { return base.Top; }
            set
            {
                base.Top = value;
                myEl.Y = value;
            }
        }

        /// <summary>
        /// Sets the height of the control
        /// </summary>
        /// <param name="h">new height</param>
        /// <remarks>don't change height of the associated element</remarks>
        public void SetHeight(int h)
        {
            base.Height = h;
        }

        /// <summary>
        /// Sets the width of the control
        /// </summary>
        /// <param name="h">new width</param>
        /// <remarks>don't change width of the associated element</remarks>
        public void SetWidth(int w)
        {
           base.Width = w;
        }


        /// <summary>
        /// Draws the Skin element
        /// </summary>
        public void DrawControl()
        {
            this.BringToFront();
            int curH = Height, curW = Width;
            btBack = new Bitmap(myEl.Width, myEl.Height);
            Graphics g = Graphics.FromImage(btBack);
            myEl.DrawElement(g);
            //if while drew element height or width changed, then it needs to draw the control again
            if (curH != myEl.Height || curW != myEl.Width)
            {
                btBack = new Bitmap(btBack, new Size(myEl.Width, myEl.Height));
                Graphics g1 = Graphics.FromImage(btBack);
                g1.Clear(BackColor);
                myEl.DrawElement(g1);
                g = g1;
            }
            Image = btBack;
            if (isSelected) g.DrawRectangle(Pens.Red, 1, 1, myEl.Width - 2, myEl.Height - 2);
        }


        /// <summary>
        /// Update the value of a property of associated XmlElement
        /// </summary>
        /// <param name="prop">XmlElementProperty object that contains new property value</param>
        public void ChangeElementProperty(XmlElementProperty prop)
        {
            PropertyInfo pi = myEl.GetType().GetProperty(prop.Name); //uses reflaction to update property value
            pi.SetValue(myEl, prop.Value, null);
            if (prop.Name.Equals("X")) this.Left = (int)prop.Value;
            if (prop.Name.Equals("Y")) this.Top = (int)prop.Value;
        }

        /// <summary>
        /// Returns the rlTodayXmlElement associated
        /// </summary>
        /// <returns>The instance of rlTodayXmlElement associated</returns>
        public rlTodayXmlElement GetTodayElement()
        {
            return myEl;
        }



        /*****************************
         PRIVATE MEMBERS
         *****************************/

    }//end class
}//end namespace